use crate::sketchbook::model::ModelState;
use biodivine_hctl_model_checker::preprocessing::hctl_tree::HctlTreeNode;
use biodivine_hctl_model_checker::preprocessing::parser::{
parse_and_minimize_hctl_formula, parse_hctl_formula,
};
use biodivine_lib_param_bn::symbolic_async_graph::SymbolicContext;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct HctlFormula {
#[serde(
serialize_with = "serialize_tree",
deserialize_with = "deserialize_tree"
)]
tree: HctlTreeNode,
}
pub fn parse_hctl_formula_wrapper(formula: &str) -> Result<HctlTreeNode, String> {
parse_hctl_formula(formula)
.map_err(|e| format!("Error during HCTL formula processing: '{}'", e))
}
pub fn parse_and_minimize_hctl_formula_wrapper(
symbolic_context: &SymbolicContext,
formula: &str,
) -> Result<HctlTreeNode, String> {
parse_and_minimize_hctl_formula(symbolic_context, formula)
.map_err(|e| format!("Error during HCTL formula processing: '{}'", e))
}
fn serialize_tree<S>(tree: &HctlTreeNode, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&tree.to_string())
}
fn deserialize_tree<'de, D>(deserializer: D) -> Result<HctlTreeNode, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
parse_hctl_formula_wrapper(&s).map_err(de::Error::custom)
}
impl fmt::Display for HctlFormula {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.tree)
}
}
impl HctlFormula {
pub fn try_from_str(formula: &str) -> Result<HctlFormula, String> {
Ok(HctlFormula {
tree: parse_hctl_formula_wrapper(formula)?,
})
}
}
impl HctlFormula {
pub fn change_formula(&mut self, new_formula: &str) -> Result<(), String> {
self.tree = parse_hctl_formula_wrapper(new_formula)?;
Ok(())
}
}
impl HctlFormula {
pub fn as_str(&self) -> &str {
&self.tree.formula_str
}
pub fn tree(&self) -> &HctlTreeNode {
&self.tree
}
}
impl HctlFormula {
pub fn check_syntax(formula: &str) -> Result<(), String> {
let res = parse_hctl_formula_wrapper(formula);
if res.is_ok() {
Ok(())
} else {
Err(res.err().unwrap())
}
}
pub fn check_syntax_with_model(formula: &str, model: &ModelState) -> Result<(), String> {
let bn = model.to_empty_bn();
let ctx = SymbolicContext::new(&bn)?;
let res: Result<HctlTreeNode, String> =
parse_and_minimize_hctl_formula_wrapper(&ctx, formula);
if res.is_ok() {
Ok(())
} else {
Err(res.err().unwrap())
}
}
}